home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 19.4 KB | 604 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWMnuBar.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWOS.hpp"
-
- #ifndef FWMNUBAR_H
- #include "FWMnuBar.h"
- #endif
-
- #ifndef FWPULLDM_H
- #include "FWPullDM.h"
- #endif
-
- // ----- Foundation Includes -----
-
- #ifndef FWSTRS_H
- #include "FWStrs.h"
- #endif
-
- #ifndef FWSOMENV_H
- #include "FWSOMEnv.h"
- #endif
-
- // ----- OS Includes -----
-
- #ifndef FWRESOUR_H
- #include "FWResour.h"
- #endif
-
- #ifndef FWMENUS_K
- #include "FWMenus.k"
- #endif
-
- // ----- ODUtil Includes -----
-
- #ifndef FWORDCOL_H
- #include "FWOrdCol.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_ODPart_xh
- #include <Part.xh>
- #endif
-
- #ifndef SOM_ODDraft_xh
- #include <Draft.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODWindowState_xh
- #include <WinStat.xh>
- #endif
-
- // ----- Macintosh Includes -----
-
- #if defined(FW_BUILD_MAC) && !defined(__TOOLUTILS__)
- #include <ToolUtils.h>
- #endif
-
- //========================================================================================
- // RunTime Info
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment fwmenu
- #endif
-
- //========================================================================================
- // class FW_CMenuBar
- //========================================================================================
-
- FW_DEFINE_AUTO(FW_CMenuBar)
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::FW_CMenuBar
- //----------------------------------------------------------------------------------------
-
- FW_CMenuBar::FW_CMenuBar(Environment* ev, ODPart* thePart, FW_Instance partInstance) :
- fODPart(thePart),
- fPullDownMenuList(NULL),
- fNextMenuID(FW_kFirstMenuID),
- fPartInstance(partInstance)
- {
- fODMenuBar = fODPart->GetStorageUnit(ev)->GetSession(ev)->GetWindowState(ev)->CopyBaseMenuBar(ev);
- fPullDownMenuList = FW_NEW(FW_TOrderedCollection<FW_CPullDownMenu>, ());
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::InitializeFromResource
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::InitializeFromResource(Environment* ev, FW_ResourceID menuBarResourceID)
- {
- // InitializeFromResource should only be called once, immediately after
- // the menu bar is created, while the menu list is still empty.
- // However, since it simply appends the menus to the end of the menubar,
- // there may be no harm in calling it more than once.
- // FW_ASSERT(fPullDownMenuList->Count() == 0);
-
- FW_TRY
- {
- FW_PSharedLibraryResourceFile resFile(ev, fPartInstance);
- FW_PResource menuBarResource(ev, resFile, menuBarResourceID, FW_kMenuBarResourceType);
- FW_PResourceSink sink(ev, menuBarResource);
- FW_CReadableStream stream(sink);
- InitializeFromStream(ev, stream);
- }
- FW_CATCH_BEGIN
- FW_CATCH_REFERENCE(FW_XException, except)
- {
- // We use this try-catch block purely to warn about a common mistake.
- // If one forgets to add the resource containing their menus to their project,
- // or passes in the wrong menu id, the above code will throw an exception
- // that probably won't get caught until the SOM entry point from OpenDoc.
- // OpenDoc will display an error dialog that isn't particularly helpful
- // in diagnosing the problem.
- FW_DEBUG_MESSAGE("Failed to load menu resource.");
- FW_PlatformError error = except.GetPlatformError();
- FW_THROW_SAME();
- }
- FW_CATCH_END
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::InitializeFromStream
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
- {
- // InitializeFromStream should only be called once, immediately after
- // the menu bar is created, while the menu list is still empty.
- // However, since it simply appends the menus to the end of the menubar,
- // there may be no harm in calling it more than once.
- // FW_ASSERT(fPullDownMenuList->Count() == 0);
-
- // This first FW_DO_NOT_DEAD_STRIP is a must, so it makes full sense to have it here.
- FW_DO_NOT_DEAD_STRIP(FW_CPullDownMenu);
-
- // These aren't absolutely required, but it would be extremely rare to have menu
- // items without Text and Separators, so for convenience we prevent them from
- // being dead stripped in any part that initializes its menus from a stream (resource).
- // However, the other kinds of menu items must be explicitly prevented from being
- // deadstripped in every part that uses them.
- FW_DO_NOT_DEAD_STRIP(FW_CTextItem);
- FW_DO_NOT_DEAD_STRIP(FW_CSeparatorItem);
-
- stream >> fAboutString;
-
- short nMenus;
- stream >> nMenus;
-
- while (nMenus-- > 0)
- {
- FW_CPullDownMenu* pullDownMenu;
- FW_READ_DYNAMIC_OBJECT(stream, &pullDownMenu, FW_CPullDownMenu);
- FW_ASSERT(pullDownMenu != 0);
- AdoptMenuLast(ev, pullDownMenu);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::~FW_CMenuBar
- //----------------------------------------------------------------------------------------
-
- FW_CMenuBar::~FW_CMenuBar()
- {
- FW_SOMEnvironment ev;
-
- if (fPullDownMenuList)
- DeleteAll(ev);
-
- if (fODMenuBar)
- fODMenuBar->Release(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::AdoptMenuFirst
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::AdoptMenuFirst(Environment* ev, FW_CPullDownMenu* menu)
- {
- FW_ASSERT(menu != NULL);
-
- FW_CPullDownMenu* first = (FW_CPullDownMenu*)fPullDownMenuList->First();
- fPullDownMenuList->AddFirst(menu);
-
- ODMenuID beforeID = first == NULL ? -1 : first->GetMenuID(ev);
- menu->PrivAttachedToMenuBar(ev, fODPart, this, beforeID);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::AdoptMenuLast
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::AdoptMenuLast(Environment* ev, FW_CPullDownMenu* menu)
- {
- FW_ASSERT(menu != NULL);
-
- fPullDownMenuList->AddLast(menu);
- menu->PrivAttachedToMenuBar(ev, fODPart, this, -1);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::AdoptMenuBefore
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::AdoptMenuBefore(Environment* ev, FW_CPullDownMenu* menu, FW_CPullDownMenu* beforeMenu)
- {
- FW_ASSERT(menu != NULL);
-
- if (beforeMenu == NULL)
- AdoptMenuFirst(ev, menu);
- else
- {
- fPullDownMenuList->AddBefore(beforeMenu, menu);
- menu->PrivAttachedToMenuBar(ev, fODPart, this, beforeMenu->GetMenuID(ev));
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::AdoptMenuAfter
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::AdoptMenuAfter(Environment* ev, FW_CPullDownMenu* menu, FW_CPullDownMenu* afterMenu)
- {
- FW_ASSERT(menu != NULL);
-
- if (afterMenu == NULL)
- AdoptMenuLast(ev, menu);
- else
- {
- FW_CPullDownMenu* next = (FW_CPullDownMenu*)fPullDownMenuList->After(afterMenu);
- fPullDownMenuList->AddAfter(afterMenu, menu);
- ODMenuID beforeID = next == NULL ? -1 : next->GetMenuID(ev);
- menu->PrivAttachedToMenuBar(ev, fODPart, this, beforeID);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::DeleteMenu
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::DeleteMenu(Environment* ev, FW_CPullDownMenu* menuToDelete)
- {
- FW_ASSERT(menuToDelete != NULL);
-
- DetachMenu(ev, menuToDelete);
- delete menuToDelete;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::DeleteAll
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::DeleteAll(Environment* ev)
- {
- FW_CPullDownMenu *menu;
- while ((menu = fPullDownMenuList->First()) != NULL)
- {
- DeleteMenu(ev, menu);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::RemoveItem
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::RemoveItem(Environment* ev, ODCommandID commandID)
- {
- FW_CMenuItem* item = this->GetMenuItemFromCommand(ev, commandID);
- FW_ASSERT(item);
-
- FW_CPullDownMenu* menu = item->GetOwnerMenu(ev);
- menu->RemoveItem(ev, item->GetIndex(ev));
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::DetachMenu
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::DetachMenu(Environment* ev, FW_CPullDownMenu* menuToDetach)
- {
- FW_ASSERT(menuToDetach != NULL);
-
- fODMenuBar->RemoveMenu(ev, menuToDetach->GetMenuID(ev));
-
- fPullDownMenuList->Remove(menuToDetach);
- menuToDetach->PrivDetachedFromMenuBar(ev, this);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::GetMenuKey
- //----------------------------------------------------------------------------------------
-
- FW_MenuKey FW_CMenuBar::GetMenuKey(Environment* ev, ODCommandID cmdNumber) const
- {
- #ifdef FW_BUILD_MAC
- FW_MenuKey menuKey;
-
- ODMenuID menuID;
- ODMenuItemID menuItem;
- fODMenuBar->GetMenuAndItem(ev, cmdNumber, &menuID, &menuItem);
-
- ::GetItemCmd(GetMenuHandle(menuID), menuItem, &menuKey);
- return menuKey;
- #endif
-
- #ifdef FW_BUILD_WIN
- return 0; // [HLX] no way yet to parse accelerator table
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::AcquireODMenuBar
- //----------------------------------------------------------------------------------------
-
- ODMenuBar* FW_CMenuBar::AcquireODMenuBar(Environment* ev) const
- {
- #if FW_OPENDOC_VERSION >= FW_OPENDOC_DR3
- fODMenuBar->Acquire(ev);
- #else
- fODMenuBar->IncrementRefCount(ev);
- #endif
- return fODMenuBar;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::FindMenuWithID
- //----------------------------------------------------------------------------------------
-
- FW_CPullDownMenu* FW_CMenuBar::FindMenuWithID(Environment* ev, ODMenuID menuID) const
- {
- // ----- Search the top level first -----
- FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
- FW_CPullDownMenu* pullDownMenu;
- for (pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
- {
- if (pullDownMenu->GetMenuID(ev) == menuID)
- return pullDownMenu;
- }
-
- // ----- Then search subMenus -----
- for (pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
- {
- FW_CPullDownMenu* menu = pullDownMenu->PrivFindMenuWithID(ev, menuID);
- if (menu)
- return menu;
- }
-
- return NULL;
- }
-
- #ifdef FW_BUILD_MAC
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::MacEnableMenuBar
- //----------------------------------------------------------------------------------------
- // This is specific for modal dialogs on the Mac
-
- void FW_CMenuBar::MacEnableMenuBar(Environment* ev, FW_Boolean enable)
- {
- // ----- Apple & OpenDoc Menus -----
- fODMenuBar->EnableCommand(ev, kODCommandAppleMenu, enable);
- fODMenuBar->EnableCommand(ev, kODCommandEditMenu, enable);
- fODMenuBar->EnableCommand(ev, kODCommandDocumentMenu, enable);
-
- // ----- Then custom menus -----
- FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
- for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
- {
- if (enable)
- ::EnableItem(GetMenuHandle(pullDownMenu->GetMenuID(ev)), 0);
- else
- ::DisableItem(GetMenuHandle(pullDownMenu->GetMenuID(ev)), 0);
- }
-
- ::InvalMenuBar();
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::EnableCommand
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::EnableCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean enable)
- {
- fODMenuBar->EnableCommand(ev, cmdNumber, enable);
-
- #ifdef FW_BUILD_MAC
- PrivMacEnableParentItem(ev, cmdNumber);
- #endif
- }
-
- #ifdef FW_BUILD_MAC
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::PrivMacEnableParentItem
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::PrivMacEnableParentItem(Environment* ev, ODCommandID cmdNumber)
- {
- ODMenuID menuID;
- ODMenuItemID menuItem;
-
- fODMenuBar->GetMenuAndItem(ev, cmdNumber, &menuID, &menuItem);
-
- FW_CPullDownMenu* menu = this->FindMenuWithID(ev, menuID);
- if (menu == NULL)
- return;
-
- FW_CMenuItem* parentItem = menu->GetParentMenuItem(ev);
-
- while (parentItem != NULL) // enable/disable parent menu
- {
- ODPlatformMenu platformMenu = menu->GetPlatformMenu(ev);
- long flags = (*platformMenu)->enableFlags;
-
- if ((flags & 0xFFFFFFFE) != 0) // If any items enabled,
- flags |= 0x00000001; // enable top level item
- else // No items enabled,
- flags = 0x00000000; // disable top level item
-
- if ((flags & 0x00000001) != ((*platformMenu)->enableFlags & 0x00000001))
- {
- (*platformMenu)->enableFlags = flags;
- }
-
- menu = parentItem->GetOwnerMenu(ev);
- ODPlatformMenu parentMenu = menu->GetPlatformMenu(ev);
- if ((flags & 0xFFFFFFFE) != 0) // if any items enabled
- ::EnableItem(parentMenu, parentItem->GetIndex(ev));
- else
- ::DisableItem(parentMenu, parentItem->GetIndex(ev));
-
- // Check parent's parent
- parentItem = menu->GetParentMenuItem(ev);
- }
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::GetMenuItemFromCommand
- //----------------------------------------------------------------------------------------
-
- FW_CMenuItem* FW_CMenuBar::GetMenuItemFromCommand(Environment* ev, ODCommandID cmdNumber) const
- {
- FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
- for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
- {
- FW_CMenuItem* menuItem = pullDownMenu->PrivGetMenuItem(ev, cmdNumber);
- if (menuItem != NULL)
- return menuItem;
- }
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::ToggleItem
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::ToggleItem(Environment* ev,
- ODCommandID cmdNumber,
- FW_Boolean toggleState)
- {
- FW_CMenuItem* menuItem = GetMenuItemFromCommand(ev, cmdNumber);
- FW_ASSERT(menuItem != NULL);
-
- #ifdef FW_DEBUG
- FW_CToggleItem* toggleItem = FW_DYNAMIC_CAST(FW_CToggleItem, menuItem);
- FW_ASSERT(toggleItem);
- toggleItem->ToggleItem(ev, toggleState);
- #else
- ((FW_CToggleItem*)menuItem)->ToggleItem(ev, toggleState);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::DisableAll
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::DisableAll(Environment* ev)
- {
- FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
- for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
- {
- pullDownMenu->DisableAll(ev);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::EnableAll
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::EnableAll(Environment* ev)
- {
- FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
- for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
- {
- pullDownMenu->EnableAll(ev);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::CheckCommand
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::CheckCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean check)
- {
- fODMenuBar->CheckCommand(ev, cmdNumber, check);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::EnableAndCheckCommand
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::EnableAndCheckCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean enable, FW_Boolean check)
- {
- fODMenuBar->EnableAndCheckCommand(ev, cmdNumber, enable, check);
-
- #ifdef FW_BUILD_MAC
- PrivMacEnableParentItem(ev, cmdNumber);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::EnableAndToggleCommand
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::EnableAndToggleCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean enable, FW_Boolean toggleState)
- {
- EnableCommand(ev, cmdNumber, enable);
- ToggleItem(ev, cmdNumber, toggleState);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::SetItemString
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::SetItemString(Environment* ev, ODCommandID commandID, const FW_CString& itemString)
- {
- fODMenuBar->SetItemString(ev, commandID, itemString.RevealODIText());
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::GetItemString
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::GetItemString(Environment* ev, ODCommandID commandID, FW_CString& itemString) const
- {
- ODIText intlText;
- fODMenuBar->GetItemString(ev, commandID, &intlText);
- itemString = &intlText;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::GetAboutString
- //----------------------------------------------------------------------------------------
- FW_CString FW_CMenuBar::GetAboutString(Environment*) const
- {
- return fAboutString;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMenuBar::SetMenuKey
- //----------------------------------------------------------------------------------------
-
- void FW_CMenuBar::SetMenuKey(Environment* ev, ODCommandID cmdNumber, FW_MenuKey menuKey)
- {
- #ifdef FW_BUILD_MAC
- ODMenuID menuID;
- ODMenuItemID menuItem;
- fODMenuBar->GetMenuAndItem(ev, cmdNumber, &menuID, &menuItem);
- MenuHandle menuHandle = ::GetMenuHandle(menuID);
- FW_ASSERT(menuHandle);
-
- // Check for an existing key code, or other code ($1B submenu; $1C script code; $1D, $1E icon)
- FW_MenuKey currentKey;
- ::GetItemCmd(menuHandle, menuItem, ¤tKey);
-
- // If the current value is a special code, don't change it
- if (currentKey == FW_kNoKeyEquivalent || currentKey > 32)
- ::SetItemCmd(menuHandle, menuItem, menuKey & FW_kPrivMacMenuKeyCharMask);
- #endif
-
- #ifdef FW_BUILD_WIN
- // [MEB] Not yet implemented
- FW_UNUSED(ev);
- FW_UNUSED(cmdNumber);
- FW_UNUSED(menuKey);
- #endif
- }
-